package cndw.core.dispatch;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;

import cndw.core.dispatch.annotation.Action;
import cndw.core.dispatch.exception.ActionNotFoundException;
import cndw.core.util.LogConst;
import cndw.core.util.annotation.NotNull;

/**
 *
 * @author zuojie.x
 */
public class ActionManager {
	private final Logger log = LoggerFactory.getLogger(LogConst.CORE);
	private final ApplicationContext context;
	
	private ActionFilterExecutor actionFilterExecutor;
	/** key:控制器名 value:控制器对象 */
	/** 控制器过滤器集合 */
	private Collection<ActionFilter> filters;
	/** 控制器 */
	private Map<Integer, ActionExecutor> actionIdMap;
	
	public ActionManager(ApplicationContext context) {
		this.context = context;
		load();
	}
	
	private void load() {
		actionIdMap = new HashMap<Integer, ActionExecutor>(64);
		filters = context.getBeansOfType(ActionFilter.class).values();
		if (log.isDebugEnabled()) {
			for (ActionFilter filter : filters)
				log.debug("load ActionFilter -> {}", filter.getClass().getName());
		}
		Map<String, Object> objects = context.getBeansWithAnnotation(Action.class);
		for (Map.Entry<String, Object> entry : objects.entrySet()) {
			Object actionObj = entry.getValue();
			for (Method method : actionObj.getClass().getDeclaredMethods()) {
				if (method.getAnnotation(Action.class) != null) {
					ActionExecutor actionHolder = new ActionExecutor(actionObj, method);
					int actionId = actionHolder.getActionId();
					if (actionId == -1)
						throw new RuntimeException("未设置Action id, action:" + actionHolder.getActionDesc());
					if (actionIdMap.containsKey(actionId))
						throw new RuntimeException("Action id 重复:" + actionId);
					actionIdMap.put(actionId, actionHolder);
					log.debug("load Action -> {}", actionHolder.getActionDesc());
				}
			}
		}
		log.debug("total Action count -> {}.", actionIdMap.size());
		actionFilterExecutor = new ActionFilterExecutor(filters);
	}
	
	/**
	 * Action执行器
	 * 
	 * @param request
	 * @return
	 * @throws ActionNotFoundException
	 */
	@NotNull
	ActionExecutor getActionExecutor(Request request) throws ActionNotFoundException {
		ActionExecutor actionHolder = actionIdMap.get(request.getActionId());
		if (actionHolder == null)
			throw new ActionNotFoundException(request.getActionId());
		return actionHolder;
	}
	
	/**
	 * @return Action过虑器执行器
	 */
	ActionFilterExecutor getActionFilterExecutor() {
		return actionFilterExecutor;
	}
}
